/*
 * Copyright (c) 2018.
 * http://www.ulabcare.com
 */

package com.mt.roll.core.base;

import com.alibaba.fastjson.JSON;
import com.mt.roll.core.enums.WhetherEnum;
import com.mt.roll.core.dto.LoginUser;
import com.mt.roll.core.vo.R;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 接口支持基类
 *
 * @author jiff
 * @date 2018/11/1
 * @since 1.0
 */
public abstract class BaseSupport {
    private static final ThreadLocal<LoginUser> loginUserHolder = new NamedThreadLocal<>("LoginUser");

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    protected LoginUser getLoginUser() {
        // 后续完善拦截器再使用该方式
//        LoginUser loginUser = loginUserHolder.get();
//        if (loginUser != null) {
//            return loginUser;
//        }
        HttpSession session = getHttpServletRequest().getSession(false);
        LoginUser loginUser = null;
        if (session != null) {
            String loginUserJson = (String) session.getAttribute(LoginUser.HTTP_HEADER_NAME);
            if (StringUtils.isNotBlank(loginUserJson)) {
                loginUser = JSON.parseObject(loginUserJson, LoginUser.class);
                return loginUser;
            }
        }
        return null;
    }

    /**
     * 获取当前http请求对象
     *
     * @return
     */
    protected HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    /**
     * 获取当前http响应对象
     *
     * @return
     */
    protected HttpServletResponse getHttpServletResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }

    /**
     * <p>
     * 请求成功
     * </p>
     *
     * @param data 数据内容
     * @param <T>  对象泛型
     * @return
     */
    protected <T> R<T> successful(T data) {
        return R.ok(data);
    }

    /**
     * <p>
     * 请求成功
     * </p>
     *
     * @param msg  提示内容
     * @param data 数据内容
     * @param <T>  对象泛型
     * @return
     */
    protected <T> R<T> successful(String msg, T data) {
        return R.ok(msg, data);
    }

    /**
     * <p>
     * 请求失败
     * </p>
     *
     * @param code 错误码
     * @param msg  提示内容
     * @param <T>  对象泛型
     * @return
     */
    protected <T> R<T> failed(int code, String msg) {
        return R.failed(code, msg);
    }

    /**
     * <p>
     * 请求失败
     * </p>
     *
     * @param msg 提示内容
     * @param <T> 对象泛型
     * @return
     */
    protected <T> R<T> failed(String msg) {
        return R.failed(msg);
    }

    /**
     * <p>
     * 请求失败
     * </p>
     *
     * @param errorCode 请求错误码
     * @param <T>       对象泛型
     * @return
     */
    protected <T> R<T> failed(IErrorCode errorCode) {
        return R.failed(errorCode);
    }

    protected R<String> addResult(boolean status) {
        return status ? successful("添加成功", null) : failed("添加失败");
    }

    protected R<String> editResult(boolean status) {
        return status ? successful("修改成功", null) : failed("修改失败");
    }

    protected R<String> delResult(boolean status) {
        return status ? successful("删除成功", null) : failed("删除失败");
    }

    protected R<String> enabledResult(boolean status) {
        return status ? successful("已启用", null) : failed("已禁用");
    }

    /**
     * 设置公共字段值，一般用于创建新记录，包含以下字段：
     *
     * <p>
     * {@link CommonField#enabled}<br>
     * {@link CommonField#valid}<br>
     * {@link CommonField#creator}<br>
     * {@link CommonField#creatorName}<br>
     * {@link CommonField#createTime}<br>
     * {@link CommonField#updater}<br>
     * {@link CommonField#updaterName}<br>
     * {@link CommonField#updateTime}<br>
     * </p>
     *
     * @param t                需要设置的对象
     * @param ignoreProperties 忽略的字段
     * @param <T>
     */
    protected <T extends Serializable> T setCommonField(T t, String... ignoreProperties) {
        CommonField commonField = CommonField.builder()
                .enabled(WhetherEnum.YES.getValue())
                .valid(WhetherEnum.YES.getValue())
                .createTime(LocalDateTime.now())
                .creator(getLoginUser().getUserId())
                .creatorName(getLoginUser().getUserName())
                .updateTime(LocalDateTime.now())
                .updater(getLoginUser().getUserId())
                .updaterName(getLoginUser().getUserName())
                .build();
        BeanUtils.copyProperties(commonField, t, ignoreProperties);
        return t;
    }

    /**
     * 设置更新的公共字段值，一般用于更新记录，包含以下字段：
     *
     * <p>
     * {@link CommonField#updater}<br>
     * {@link CommonField#updaterName}<br>
     * {@link CommonField#updateTime}<br>
     * </p>
     *
     * @param t   需要设置的对象
     * @param <T>
     */
    protected <T extends Serializable> T setUpdateCommonField(T t) {
        CommonField commonField = CommonField.builder()
                .updater(getLoginUser().getUserId())
                .updaterName(getLoginUser().getUserName())
                .updateTime(LocalDateTime.now())
                .build();
        BeanUtils.copyProperties(commonField, t, "enabled", "valid");
        return t;
    }

    @Data
    @Builder
    private static class CommonField implements Serializable {
        /**
         * 启用状态:0 、停用，1、启用
         */
        private Integer enabled;
        /**
         * 删除标志，是否有效:1 可用 0不可用
         */
        private Integer valid;


        /**
         * 创建人
         */
        private Long creator;
        /**
         * 创建人
         */
        private String creatorName;
        /**
         * 创建时间
         */
        private LocalDateTime createTime;


        /**
         * 更新人
         */
        private Long updater;
        /**
         * 更新人
         */
        private String updaterName;
        /**
         * 更新时间
         */
        private LocalDateTime updateTime;
    }
}
